package com.may.wind.handler;

import com.may.wind.enums.ResultEnum;
import com.may.wind.exception.GlobalRunningException;
import com.may.wind.pojo.Result;
import com.may.wind.util.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.HttpClientErrorException;

/**
 * 使用统一返回结果时，还有一种情况，就是程序的保存是由于运行时异常导致的结果，有些异常我们可以无法提前预知，不能正常走到我们return的R对象返回
 * 该类中的设计思路：
 * 使用@ExceptionHandler注解捕获指定或自定义的异常
 * 使用@ControllerAdvice集成@ExceptionHandler的方法到一个类中
 * 必须定义一个通用的异常捕获方法，便于捕获未定义的异常信息
 */
@ControllerAdvice
//该注解为统一异常处理的核心,是一种作用于控制层的切面通知（Advice），该注解能够将通用的@ExceptionHandler、@InitBinder和@ModelAttributes方法收集到一个类型，并应用到所有控制器上
public class GlobalExceptionHandler {
    private final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * -------- 通用异常处理方法 --------
     **/
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result error(Exception exception) {
        // 通用异常结果打印到日志
        logger.error(ExceptionUtil.getMessage(exception));
        return Result.error();
    }

    /**
     * -------- 指定异常处理方法 --------
     **/
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public Result error(NullPointerException exception) {
        exception.printStackTrace();
        return Result.setResult(ResultEnum.NULL_POINT);
    }

    @ExceptionHandler(HttpClientErrorException.class)
    @ResponseBody
    public Result error(IndexOutOfBoundsException exception) {
        exception.printStackTrace();
        return Result.setResult(ResultEnum.HTTP_CLIENT_ERROR);
    }

    /**
     * -------- 自定义定异常处理方法 --------
     **/
    @ExceptionHandler(GlobalRunningException.class)
    @ResponseBody
    public Result error(GlobalRunningException exception) {
        exception.printStackTrace();
        return Result.error().message(exception.getMessage()).code(exception.getCode());
    }
}
